<?php


namespace app\controller\api;

use app\common\model\SchoolModel;
use app\common\service\face\FaceDevice;
use app\common\model\CacheRefreshHandler;
use app\common\service\redis\PoolRedis;
use app\model\AdminStaffActiveCount;
use app\model\AdminStaffData;
use app\model\AdminStaffIcCard;
use app\model\AdminStaffIcCardPool;
use app\model\AdminStudentDormitory;
use app\util\ReturnCode;
use app\util\Strs;
use app\util\Tools;
use app\validate\AdminIcCardPool;
use app\validate\AdminStaff;
use app\model\AdminStaff as StaffModel;
use think\exception\ValidateException;
use think\facade\Filesystem;
use think\facade\Log;
use think\facade\Request;
use think\facade\Validate;
use think\Response;

class Staff extends Base
{
    /**
     * @func apply
     * @method POST
     * @desc 个人资料提交审核
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Time: 2021/12/7 14:59
     */
    public function apply() : Response {
        try {
            validate(AdminStaff::class)->scene('v3Edit')
                ->append('phone|手机号', 'require')->check(input('post.'));
        } catch (ValidateException $e) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $e->getError());
        }
        $postData = $this->request->post();
        if(!isset($postData['student_dormitory_id']) || $postData['student_dormitory_id'] <= 0){
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '请选择宿舍号');
        }
        $where['is_delete'] = 0;
        if (isset($postData['uuid'])) {
            // 重新审核携带
            $where['uuid'] = $postData['uuid'];
        } else {
            $where['phone'] = $postData['phone'];
        }
        $staff = (new StaffModel())->where($where)->find();
        if (!isset($postData['uuid']) && $staff) {
            return $this->buildFailed(ReturnCode::DATA_EXISTS, '手机号已被使用');
        }
        if (isset($postData['uuid']) && !$staff) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '账户未找到');
        }
        if ($staff && $staff->status == StaffModel::AUDIT_PASS) {
            return $this->buildFailed(ReturnCode::UPDATE_FAILED, '账号已审核通过，请前往登录');
        }

        if (!$staff) {
            $staff = new StaffModel();
            $postData['uuid'] = substr(Strs::uuid(), 1, -1);
            $postData['password'] = Tools::userMd5(substr($postData['phone'], -6));
            // 判断毕业时间必须打印今天
            $graduate_day = Tools::getNextMonth($postData['graduate_time']);
            $endTime = strtotime($graduate_day[0]." 00:00:00");
            if ($endTime < time()) {
                return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '毕业时间必须大于今天');
            }
        }
        $postData['type'] = StaffModel::STUDENT;
        $school = SchoolModel::getSchool($postData['school_id']);
        if ($school && $school->account_audit == 0){
            $postData['status'] = StaffModel::AUDIT_PASS;
        } else {
            $postData['status'] = StaffModel::AUDIT_WAITING;
        }
        if ($staff->save($postData) === false) {
            return $this->buildFailed(ReturnCode::DB_SAVE_ERROR);
        }
        $where = [
            'school_id' => $staff->school_id,
            'id' => $postData['student_dormitory_id'],
            'is_delete' => 0
        ];
        $studentDormitory = AdminStudentDormitory::where($where)->find();
        if ($studentDormitory) {
            AdminStaffIcCard::create([
                'school_id' => $staff->school_id,
                'dormitory_id' => $studentDormitory->dormitory_id,
                'student_dormitory_id' => $studentDormitory->id,
                'staff_id' => $staff->id,
                'lock_permission' => '1,2,3,4'
            ]);
        }
        return $this->buildSuccess([
            'audit' => $school->account_audit
        ]);
    }

    /**
     * @func edit
     * @method POST
     * @desc 个人资料更新
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Time: 2021/12/14 14:53
     */
    public function edit() : Response {
        try {
            validate(AdminStaff::class)->scene('v3Edit')
                ->append('uuid|用户标识', 'require')
                ->check(input('post.'));
        } catch (ValidateException $e) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $e->getError());
        }
        $postData = Request::only(['name','sex','school_id','student_no','major','entrance_time','graduate_time','uuid']);
        $staff = (new StaffModel())->where('uuid', $postData['uuid'])
            ->where('is_delete', 0)
            ->where('status', StaffModel::AUDIT_PASS)->find();
        if (!$staff) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '账户未找到');
        }
        if ($staff->save($postData) === false) {
            return $this->buildFailed(ReturnCode::DB_SAVE_ERROR);
        }
        return $this->buildSuccess();
    }

    /**
     * @func account
     * @method GET
     * @desc 个人资料获取
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Time: 2021/12/7 18:06
     */
    public function account() : Response {
        $staff = StaffModel::with([
            'class',
            'school'
        ])->where('uuid', input('get.uuid'))
            ->hidden(['password','is_delete'])
            ->append(['status_text','type_text'])
            ->find();
        if (!$staff) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '账号不存在');
        }
        if ($staff->is_delete == 1) {
            return $this->buildFailed(ReturnCode::AUTH_ERROR, '账号已删除，请联系管理员');
        }
        if ($staff->type == 0 && $staff->expire_flag) {
            return $this->buildFailed(ReturnCode::AUTH_ERROR, '账号已过期，无法登录');
        }
        $infoData = $staff->toArray();
        unset($infoData['school']);
        $infoData['avatar_name'] = $infoData['avatar_url'];
        $infoData['avatar_url'] = $infoData['avatar_url'] ? $this->request->domain() . $infoData['avatar_url'] : '';
        $infoData['face_url'] = $infoData['face'] ? $this->request->domain() . $infoData['face'] : '';
        $infoData['school_name'] = $staff->school_name;
        $infoData['checkIn'] = [];
        CacheRefreshHandler::userActive($staff->id);
        AdminStaffActiveCount::saveLog($staff->id, $staff->school_id, $staff->sex);
        return $this->buildSuccess($infoData);
    }

    // 学生查询
    public function search(): Response {
        $school_id = $this->request->get('school_id', null);
        $flag = $this->request->get('flag', 1);
        $keyword = $this->request->get('keyword', '');
        if (!$keyword) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, '请填写搜索数据');
        }
        $staff = StaffModel::where('is_delete', 0);
        if ($school_id) {
            $staff->where('school_id', $school_id);
        }
        if ($flag == 1) {
            $staff->where('student_no', $keyword);
        } elseif ($flag == 2) {
            $staff->where('phone', $keyword);
        }

        $staff = $staff->with('school')
            ->field('id,status,uuid,school_id,name,sex,student_no,phone,entrance_time,graduate_time,major,avatar_url')
            ->find();
        if (!$staff) {
            return $this->buildSuccess([], '没有找到相应的学生数据');
        }
        $staff = $staff->toArray();
        $staff['avatar_name'] = $staff['avatar_url'];
        $staff['avatar_url'] = $staff['avatar_url'] ? $this->request->domain() . $staff['avatar_url'] : '';

        return $this->buildSuccess($staff);
    }

    /**
     * @notes: 通过用户uuid查询宿舍所有学生信息
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author: speed
     */
    public function searchInDormitory() : Response {
        $getData = Request::only(['uuid', 'student_dormitory_id']);
        $validate = Validate::rule([
            'uuid'  => 'require',
            'student_dormitory_id|宿舍号ID' => 'number',
        ]);
        if (!$validate->check($getData)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $staff = StaffModel::where('is_delete', 0)
            ->where('uuid', $getData['uuid'])
            ->where('type', StaffModel::STUDENT)
            ->field('id,school_id')
            ->find();
        if (!$staff) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '账户未找到');
        }
        $student_dormitory_query = AdminStaffIcCard::where([
                'school_id' => $staff->school_id,
                'staff_id' => $staff->id,
                'is_delete' => 0
            ])->field('student_dormitory_id')->buildSql();

        $query = AdminStaffIcCard::alias('ic')->with('school')
            ->join([$student_dormitory_query => 'sd'], 'sd.student_dormitory_id=ic.student_dormitory_id')
            ->join(['admin_staff' => 's'], 's.id=ic.staff_id')
            ->where([
                'ic.school_id' => $staff->school_id,
                'ic.is_delete' => 0,
                's.is_delete' => 0,
                's.type' => StaffModel::STUDENT
            ]);
        if ($getData['student_dormitory_id']) {
            $query->where('ic.student_dormitory_id', $getData['student_dormitory_id']);
        }

        $student_dormitory_list = $query
            ->field('ic.dormitory_id,ic.student_dormitory_id,s.id,status,uuid,s.school_id,name,sex,student_no,phone,entrance_time,graduate_time,major,avatar_url')
			->order('s.id')
            ->select();
        if (!$student_dormitory_list) {
            return $this->buildSuccess([], '没有找到相应的学生数据');
        }
		$student_dormitory_list = $student_dormitory_list->toArray();
        foreach ($student_dormitory_list as $key => $item) {
            $student_dormitory_list[$key]['avatar_name'] = $item['avatar_url'];
            $student_dormitory_list[$key]['avatar_url'] = $item['avatar_url'] ? $this->request->domain() . $item['avatar_url'] : '';
        }
        return $this->buildSuccess($student_dormitory_list);
    }

    /**
     * @func synchronize
     * @method POST
     * @desc sim卡或ic卡激活同步
     * @param type 1--sim卡 2--ic卡 3--模块白名单编号
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Time: 2021/12/29 18:09
     */
    public function synchronize() : Response {
        $postData = Request::only(['uuid','type','card','student_dormitory_id']);
        $validate = Validate::rule([
            'uuid'  => 'require',
            'type|类型' => 'require|in:1,2,3',
            'card|卡号' => 'max:20|require',
            'student_dormitory_id|宿舍号' => 'require',
        ]);
        if (!$validate->check($postData)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        //Log::error("同步卡：".$postData["card"]);
        $staff = (new StaffModel())->where('uuid', $postData['uuid'])
            ->where('is_delete', 0)
            ->where('status', StaffModel::AUDIT_PASS)->find();
        if ($staff) {
            // 通过uuid查找
            $ic_card = AdminStaffIcCard::where([
                'staff_id' => $staff->id,
                'school_id' => $staff->school_id,
                'student_dormitory_id' => $postData['student_dormitory_id'],
                'is_delete' => 0
            ])->find();
        } else {
            // 通过卡查找
            $ic_card = AdminStaffIcCard::where([
                'ic_card' => $postData['card'],
                'school_id' => $staff->school_id,
                'student_dormitory_id' => $postData['student_dormitory_id'],
                'is_delete' => 0
            ])->find();
        }
        if (!$ic_card) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '没有该宿舍权限，请联系管理员');
        }
        switch ($postData['type']) {
            case 1:
                // 20240614 不覆盖后台的
                //$staff->sim_card = $postData['card'];
                $ic_card->sim_activate_time = time();
                break;
            case 2:
//                if ($staff->type == StaffModel::STUDENT) {
//                    $staff->smart_card = $postData['card'];
//                }
                // 20240614 不覆盖后台的
                //$ic_card->ic_card = $postData['card'];
                $ic_card->activate_time = time();
                break;
            case 3:
                $ic_card->whitelist_no = $postData['card'];
                break;
            default:
                return $this->buildFailed(ReturnCode::INVALID);
        }
        // $staff->save() === false ||
        if ($ic_card->save() === false) {
            return $this->buildFailed(ReturnCode::DB_SAVE_ERROR);
        }
        if (in_array($postData['type'], [1,2])) {
            $redis = PoolRedis::instance();
            $redis->hSetNx("smartCards", $postData['card'], $staff->id);
        }
        return $this->buildSuccess();
    }

    public function IcCardList() : Response {
        $data = Request::only(['page','uuid','type']);
        $validate = Validate::rule([
            'uuid|用户'  => 'require',
            'type|类型' => 'require|in:1,2',
            'page|页码' => 'number',
        ]);
        if (!$validate->check($data)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $staff = (new StaffModel())->where([
                'uuid' => $data['uuid'],
                'is_delete' => 0,
            ])
            ->where('status', StaffModel::AUDIT_PASS)->find();
        if (!$staff) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '账户未找到');
        }

        $query = AdminStaffIcCard::where([
                'school_id' => $staff->school_id,
                'staff_id' => $staff->id,
                'is_delete' => 0
            ])->with(['dormitory','student']);
        if ($data['type'] == 1) {
            $query->field('id,school_id,dormitory_id,student_dormitory_id,sim_uid,whitelist_no,sim_activate_time');
        } else {
            $query->field('id,school_id,dormitory_id,student_dormitory_id,ic_card,whitelist_no,activate_time,create_time');
        }
        $listObj = $query->paginate(['page' => $data['page'], 'list_rows' => config('apiadmin.ADMIN_LIST_DEFAULT')])
            ->toArray();
        foreach ($listObj['data'] as &$datum) {
            // 南华工贸 直接显示已激活
            if($datum['school_id'] == 22){
                $datum['activate_time'] = '已激活';
                $datum['sim_activate_time'] = '已激活';
            }
        }
        return $this->buildSuccess([
            'list'  => $listObj['data'],
            'count' => $listObj['total']
        ]);
    }

    public function IcCardAdd() : Response {
        $data = Request::only(['uuid','ic_number','captcha']);
        $validate = Validate::rule([
            'uuid|用户编号'  => 'require',
            'ic_number|卡编号'  => 'require',
            'captcha|验证码'  => 'require'
        ]);
        if (!$validate->check($data)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $staff = (new StaffModel())->where([
            'uuid' => $data['uuid'],
            'is_delete' => 0,
        ])->where('status', StaffModel::AUDIT_PASS)->find();
        if (!$staff) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '账户未找到');
        }

        $card = AdminStaffIcCard::where([
            'staff_id' => $staff->id,
            'is_delete' => 0
        ])->find();
        if (!$card) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '没有授权宿舍，请联系管理员');
        }

        $cardPool = AdminStaffIcCardPool::where([
            'school_id' => $staff->school_id,
            'ic_number' => $data['ic_number'],
            'captcha' => $data['captcha']
        ])->find();
        if (!$cardPool) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '卡编号或验证码不正确');
        }
        if (!$cardPool->status == 0) {
            return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '当前卡已被使用');
        }

        // 批量修改IC卡
        $update['ic_card'] = $cardPool->ic_card;
        $update['activate_time'] = 0;
        AdminStaffIcCard::update($update, [
            'staff_id' => $staff->id,
            'is_delete' => 0
        ]);

        $cardPool->status = 1;
        $cardPool->save();

        if ($staff->type == StaffModel::STUDENT) {
            $staff->smart_card = $cardPool->ic_card;
            if (!$staff->save()) {
                return $this->buildFailed(ReturnCode::DB_SAVE_ERROR);
            }
        }
        FaceDevice::editPerson($staff->id);
        return $this->buildSuccess();
    }

    public function IcCardDel() : Response {
        $data = Request::only(['id','type']);
        $validate = Validate::rule([
            'id|编号'  => 'require',
            'type|类型' => 'require|in:1,2',
        ]);
        if (!$validate->check($data)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $card = AdminStaffIcCard::where('id', $data['id'])->where('is_delete', 0)->find();
        if (!$card) {
            return $this->buildFailed(ReturnCode::NOT_EXISTS);
        }
        if ($data['id'] == 1){
            $card->sim_activate_time = 0;
            $card->sim_uid = '';
        } else {
            $card->activate_time = 0;
            $card->ic_card = '';
        }
        $card->save();
        FaceDevice::editPerson($card->staff_id);
        return $this->buildSuccess();
    }

    /**
     * @func faceSync
     * @method POST
     * @desc 用户人脸图片上传(base64格式)
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @Time: 2022/3/29 15:13
     */
    public function faceSync() : Response {
        $postData = input('post.');
        $validate = Validate::rule([
            'uuid|用户唯一标识' => 'require',
        ]);
        if (!$validate->check($postData)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $file = request()->file('face_image');
        try {
            validate(['image'=>'fileSize:20480|fileExt:jpg,jpeg,png'])
                ->check([$file]);

            $staff = (new StaffModel())->where('uuid', $postData['uuid'])
                ->where('is_delete', 0)
                ->where('status', StaffModel::AUDIT_PASS)->find();
            if (!$staff) {
                return $this->buildFailed(ReturnCode::RECORD_NOT_FOUND, '账户未找到');
            }

            $fileName = $staff->id.".jpg";
            $savename = \think\facade\Filesystem::disk('public')->putFileAs( 'faces', $file, $fileName);

            $staff->face = "/upload/".$savename;
            if ($staff->save()) {
                FaceDevice::editPerson($staff->id);
                return $this->buildSuccess();
            }
            return $this->buildFailed(ReturnCode::DB_SAVE_ERROR);
        } catch (\think\exception\ValidateException $e) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $e->getMessage());
        }
    }

    /**
     * @notes: 绑定设备信息
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author: speed
     */
    public function bindDeviceInfo(): Response {
        $data = input('get.');
        $validate = Validate::rule([
            'uuid|用户标识' => 'require',
        ]);
        if (!$validate->check($data)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $parent_data = AdminStaffData::hasWhere('staff', function($query) use($data) {
            $query->where('uuid', $data['uuid'])->where('is_delete', 0);
        })->whereIn('bind_device_status', '1,2')
            ->find();

        if (!$parent_data) {
            return $this->buildSuccess();
        }
        $device = $parent_data->visible(['last_login_device_id', 'last_login_device_name','last_bind_device_time', 'bind_device_status'])
            ->append(['status_text'])->toArray();
        return $this->buildSuccess($device);
    }

    /**
     * @notes: 绑定设备申请解绑
     * @return Response
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author: speed
     */
    public function unbindDevice(): Response {
        $data = input('get.');
        $validate = Validate::rule([
            'uuid|用户标识' => 'require',
        ]);
        if (!$validate->check($data)) {
            return $this->buildFailed(ReturnCode::PARAM_INVALID, $validate->getError());
        }
        $parent_data = AdminStaffData::hasWhere('staff', function($query) use($data) {
            $query->where('uuid', $data['uuid'])->where('is_delete', 0);
        })->whereIn('bind_device_status', '1,2')->find();

        if (!$parent_data) {
            return $this->buildFailed(ReturnCode::NOT_EXISTS, '记录不存在或已解绑');
        }
        $parent_data->bind_device_status = 2;
        $parent_data->save();
        return $this->buildSuccess();
    }
}